﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace BlueLotus7.Common
{
    public class SecurityUtility
    {
        private static SecurityUtility instance = new SecurityUtility();
        public static SecurityUtility Instance
        {
            get
            {
                return instance;
            }
        }
        private SecurityUtility() { }

        #region 3DES

        public string Encrypt3DES(string content, string encryptKey)
        {
            return Encrypt3DES(content, encryptKey, CipherMode.ECB, Encoding.ASCII);
        }
        public string Encrypt3DES(string content, string encryptKey, CipherMode cipherMode, Encoding encoding)
        {
            string result = null;

            if (!string.IsNullOrWhiteSpace(content) && !string.IsNullOrWhiteSpace(encryptKey) && encoding != null)
            {
                TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

                DES.Key = ASCIIEncoding.ASCII.GetBytes(encryptKey);
                DES.Mode = cipherMode;

                ICryptoTransform DESEncrypt = DES.CreateEncryptor();

                byte[] Buffer = encoding.GetBytes(content);
                result = Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
            }
            return result;
        }
        public string Decrypt3DES(string content, string encryptKey)
        {
            return Decrypt3DES(content, encryptKey, CipherMode.ECB, Encoding.ASCII);
        }
        public string Decrypt3DES(string content, string encryptKey, CipherMode cipherMode, Encoding encoding)
        {
            string result = null;

            if (!string.IsNullOrWhiteSpace(content) && !string.IsNullOrWhiteSpace(encryptKey) && encoding != null)
            {
                TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

                DES.Key = ASCIIEncoding.ASCII.GetBytes(encryptKey);
                DES.Mode = cipherMode;
                DES.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

                ICryptoTransform DESDecrypt = DES.CreateDecryptor();

                try
                {
                    byte[] Buffer = Convert.FromBase64String(content);
                    result = encoding.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
                }
                catch { }
            }

            return result;
        }

        #endregion

        #region RSA

        public string EncryptRSA(string content, out string public_Key, out string private_Key)
        {
            public_Key = string.Empty;
            private_Key = string.Empty;
            UnicodeEncoding ByteConverter = new UnicodeEncoding();
            byte[] DataToEncrypt = ByteConverter.GetBytes(content);
            try
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                public_Key = Convert.ToBase64String(RSA.ExportCspBlob(false));
                private_Key = Convert.ToBase64String(RSA.ExportCspBlob(true));

                //OAEP padding is only available on Microsoft Windows XP or later.  
                byte[] bytes_Cypher_Text = RSA.Encrypt(DataToEncrypt, false);
                public_Key = Convert.ToBase64String(RSA.ExportCspBlob(false));
                private_Key = Convert.ToBase64String(RSA.ExportCspBlob(true));
                return Convert.ToBase64String(bytes_Cypher_Text);
            }
            catch { return null; }
        }

        public string DecryptRSA(string content, string private_Key)
        {
            byte[] DataToDecrypt = Convert.FromBase64String(content);
            try
            {
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                //RSA.ImportParameters(RSAKeyInfo);
                byte[] bytes_Public_Key = Convert.FromBase64String(private_Key);
                RSA.ImportCspBlob(bytes_Public_Key);

                //OAEP padding is only available on Microsoft Windows XP or later.  
                byte[] bytes_Plain_Text = RSA.Decrypt(DataToDecrypt, false);
                UnicodeEncoding ByteConverter = new UnicodeEncoding();
                return ByteConverter.GetString(bytes_Plain_Text);
            }
            catch { return null; }
        }

        #endregion RSA

        #region DES

        public string EncryptDES(string content, string encryptKey)
        {
            string result = null;

            if (!string.IsNullOrWhiteSpace(content) && !string.IsNullOrWhiteSpace(encryptKey))
            {
                using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
                {
                    byte[] inputByteArray = Encoding.UTF8.GetBytes(content);
                    des.Key = ASCIIEncoding.ASCII.GetBytes(encryptKey);
                    des.IV = ASCIIEncoding.ASCII.GetBytes(encryptKey);
                    System.IO.MemoryStream ms = new System.IO.MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(inputByteArray, 0, inputByteArray.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    string str = Convert.ToBase64String(ms.ToArray());
                    ms.Close();
                    result = str;
                }
            }

            return result;
        }

        public string DecryptDES(string content, string encryptKey)
        {
            string result = null;

            if (!string.IsNullOrWhiteSpace(content) && !string.IsNullOrWhiteSpace(encryptKey))
            {
                byte[] inputByteArray = Convert.FromBase64String(content);
                using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
                {
                    des.Key = ASCIIEncoding.ASCII.GetBytes(encryptKey);
                    des.IV = ASCIIEncoding.ASCII.GetBytes(encryptKey);
                    System.IO.MemoryStream ms = new System.IO.MemoryStream();
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
                    {
                        cs.Write(inputByteArray, 0, inputByteArray.Length);
                        cs.FlushFinalBlock();
                        cs.Close();
                    }
                    string str = Encoding.UTF8.GetString(ms.ToArray());
                    ms.Close();
                    result = str;
                }
            }
            return result;
        }

        #endregion

        #region My security

        private byte[] GenerateRandomDESKey()
        {
            return EncodingUtility.Instance.GetRndHex(desKeyLength);
        }

        private byte[] GenerateRandom3DESKey()
        {
            return EncodingUtility.Instance.GetRndHex(tripleDesKeyLength);
        }


        const int desKeyLength = 48;
        public string EncryptStringDES(string content)
        {
            if (!string.IsNullOrWhiteSpace(content))
            {

            }
            return null;
        }

        public string DecryptStringDES(string content)
        {
            return null;
        }


        const int tripleDesKeyLength = 24;
        public string RynnEncrypt3DESASCII(string content)
        {
            return RynnEncrypt3DES(content, ASCIIEncoding.ASCII);
        }
        public string RynnEncrypt3DESUTF8(string content)
        {
            return RynnEncrypt3DES(content, Encoding.UTF8);
        }
        public string RynnEncrypt3DESDefault(string content)
        {
            return RynnEncrypt3DES(content, Encoding.Default);
        }
        public string RynnEncrypt3DESUnicode(string content)
        {
            return RynnEncrypt3DES(content, Encoding.Unicode);
        }
        private string RynnEncrypt3DES(string content, Encoding encoding)
        {
            string result = content;
            if (!string.IsNullOrWhiteSpace(content))
            {
                byte[] keyBytes = GenerateRandom3DESKey();
                TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

                DES.Key = keyBytes;
                DES.Mode = CipherMode.ECB;
                DES.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

                ICryptoTransform DESEncrypt = DES.CreateEncryptor();

                try
                {
                    byte[] buffer = encoding.GetBytes(content);
                    buffer = DESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length);
                    List<byte> data = new List<byte>(keyBytes);
                    data.AddRange(buffer);
                    result = Convert.ToBase64String(data.ToArray());
                }
                catch { }
            }

            return result;
        }

        public string RynnDecrypt3DESASCII(string content)
        {
            return RynnDecrypt3DES(content, ASCIIEncoding.ASCII);
        }
        public string RynnDecrypt3DESUTF8(string content)
        {
            return RynnDecrypt3DES(content, Encoding.UTF8);
        }
        public string RynnDecrypt3DESDefault(string content)
        {
            return RynnDecrypt3DES(content, Encoding.Default);
        }
        public string RynnDecrypt3DESUnicode(string content)
        {
            return RynnDecrypt3DES(content, Encoding.Unicode);
        }
        private string RynnDecrypt3DES(string content, Encoding encoding)
        {
            string result = content;
            if (!string.IsNullOrWhiteSpace(content))
            {
                try
                {
                    byte[] buffer = Convert.FromBase64String(content);
                    List<byte> bytes = new List<byte>(buffer);
                    TripleDESCryptoServiceProvider DES = new TripleDESCryptoServiceProvider();

                    DES.Key = bytes.GetRange(0, tripleDesKeyLength).ToArray();
                    buffer = bytes.GetRange(tripleDesKeyLength, bytes.Count - tripleDesKeyLength).ToArray();
                    DES.Mode = CipherMode.ECB;
                    DES.Padding = System.Security.Cryptography.PaddingMode.PKCS7;

                    ICryptoTransform DESDecrypt = DES.CreateDecryptor();
                    buffer = DESDecrypt.TransformFinalBlock(buffer, 0, buffer.Length);
                    result = encoding.GetString(buffer);
                }
                catch { }
            }

            return result;
        }
        #endregion
    }
}
